#ifndef MQINVOKER_H
#define MQINVOKER_H
#include <cJSON.h>
#include "ThmarMqttClient.h"
#include "thmar_types.h"
#include "thmar_config.h"

#define THRIFT_PROTOCOL_VERSION 1
#define THRIFT_MESSAGE_CALL 1
#define THRIFT_MESSAGE_REPLY 2
#define THRIFT_MESSAGE_EXCEPTION 3
#define THRIFT_MESSAGE_ONEWAY 4

#ifdef __cplusplus
extern "C" {
#endif
/* 默认获取响应通道名的回调函数 */
const char* thmar_default_get_ack_channel();
#ifdef __cplusplus
}
#endif

/** 异步调用响应回调函数 */
typedef void (*MQ_ONRESPONSE)(void* context, cJSON* response);

/** 获取客户端ID的回调函数 */
typedef const char* (*THMAR_GET_CLIENT_ID)();
/** 获取响应通道名的回调函数 */
typedef const char* (*THMAR_GET_ACK_CHANNEL)();
/** MqInvoker 客户端配置 */
typedef struct MqInvoker_options{
    /* 同步调用请求超时时间(秒) */
    int requestTimeout; 
    /** 对于异常，是否只输出简要错误信息 */
    int thinError;
    /* 获取响应通道名的回调函数,应用层可以自定义实现，如果没有定义则使用默认实现 */
    THMAR_GET_ACK_CHANNEL getAckChannel_f; 
} MqInvoker_options;


/** 客户端配置的默认值 */
#define MqInvoker_options_initializer { 10, 0, thmar_default_get_ack_channel }

/* MQInvoker 客户端C++封装 */
#ifdef __cplusplus
namespace  thmar{

/** MqInvoker 客户端[线程安全] */
/** 该类用于调用 RPC 服务端的方法，并从ack频道获取返回值，数据交换使用JSON格式 */
class MqInvoker{
private:
    smq::ThmarMqttClient* client;
    /* 保存getAckChannel() 的结果 */
    const char* ackChannel;
    MqInvoker_options options;
    /** 初始化响应频道 */
    void initAckChannel();
public:
    /** 构造函数 */
    /* client: MQ 客户端实例,对象析构时会自动释放 */
    /* options: 客户端配置 */
    MqInvoker(smq::ThmarMqttClient *client, const MqInvoker_options &options = MqInvoker_options_initializer);
    ~MqInvoker();
    /* 异步调用 RPC 服务端 */ 
    /* requestChannel: 请求通道名 */ 
    /* methodName: RPC 方法名 */ 
    /* args: 请求参数(json格式),为 NULL 表示无参数 */ 
    /* context: 回调函数的上下文 */ 
    /* responseCallback: 回调函数, 接收服务端响应参数(json格式) */ 
    /* 返回0表示成功, 否则返回错误码 */ 
    /* 注意: 该函数不会等待服务端响应, 而是立即返回, 回调函数会在服务端响应时被调用 */
    int asyncCall(const char *requestChannel, const char *methodName, const cJSON *args, void *context, MQ_ONRESPONSE responseCallback);
    /* 同步调用 RPC 服务端 */
    /* requestChannel: 请求通道名 */
    /* methodName: RPC 方法名 */
    /* args: 请求参数(json格式),为 NULL 表示无参数 */
    /* response: [out]接收服务端响应参数(json格式)(非NULL),调用者负责释放内存 */
    /** 返回JSON格式 */
    /** 调用成功                      */
    /** { "success": $返回值 }        */
    /** 调用成功返回NULL               */
    /** { "success": {} }             */
    /** 调用失败                       */
    /** { "exception": { $异常对象信息 } } */
    /** { "message":  $错误信息  } */
    /* 返回0表示成功, 否则返回错误码     */
    int syncCall(const char* requestChannel,const char* methodName, const cJSON* args,cJSON** response);
    /* 启动 MQ 客户端 */ 
    /* 返回0表示成功, 否则返回错误码 */ 
    int start();
    /* 停止 MQ 客户端 */ 
    void stop();
    /** 获取请求响应频道名 */
    const char* getAckChannel();
    void printOptions();
    /** 获取客户端配置 */
    const MqInvoker_options& getOptions();

};
}  // namespace thmar
#endif // __cplusplus

/* 如下是MqInvoker的C接口 */
#ifdef __cplusplus
extern "C" {
#endif

/* 定义MqInvoker类型的指针类型 */
typedef void* thmar_mq_invoker_t;

/* 创建MqInvoker客户端实例 */
/* client: MQ 客户端实例 */
/* options: 客户端配置 */
/* 成功返回: 非空指针 */
/* 失败返回: NULL */
THMAR_API thmar_mq_invoker_t thmar_mq_invoker_create(thmar_mqtt_client_t client, const MqInvoker_options* options);

/* 销毁MqInvoker客户端实例 */
THMAR_API void thmar_mq_invoker_destroy(thmar_mq_invoker_t invoker);

/* 异步调用 RPC 服务端 */
/* invoker: MqInvoker 客户端实例 */
/* requestChannel: 请求通道名 */
/* methodName: RPC 方法名 */
/* args: 请求参数(json格式),为 NULL 表示无参数 */
/* context: 回调函数的上下文 */
/* responseCallback: 回调函数, 接收服务端响应参数(json格式) */
/* 成功返回: 0 */
/* 失败返回: 错误码 */
THMAR_API int thmar_mq_invoker_async_call(thmar_mq_invoker_t invoker, const char* requestChannel, const char* methodName, const cJSON* args, void* context, MQ_ONRESPONSE responseCallback);

/* 同步调用 RPC 服务端 */
/* invoker: MqInvoker 客户端实例 */
/* requestChannel: 请求通道名 */
/* methodName: RPC 方法名 */
/* args: 请求参数(json格式),为 NULL 表示无参数 */
/* response: [out]接收服务端响应参数(json格式)(非NULL),调用者负责释放内存 */
/* 成功返回: 0 */
/* 失败返回: 错误码 */
THMAR_API int thmar_mq_invoker_sync_call(thmar_mq_invoker_t invoker, const char* requestChannel, const char* methodName, const cJSON* args, cJSON** response);

/* 启动 MQ 客户端 */
/* invoker: MqInvoker 客户端实例 */
/* 成功返回: 0 */
/* 失败返回: 错误码 */
THMAR_API int thmar_mq_invoker_start(thmar_mq_invoker_t invoker);

/* 打印客户端配置 */
THMAR_API void thmar_mq_invoker_print_options(thmar_mq_invoker_t invoker);

#ifdef __cplusplus
}
#endif

#endif // MQINVOKER_H